class Compiler {
    constructor(vm) {
        this.vm = vm;
        this.el = vm.$el;
        this.compile(this.el);
    }
    compile(el) {
        let childs = el.childNodes;
        childs.forEach(node => {
            if (this.isElement(node)) {
                this.compileElement(node);
            } else if (this.isText(node)) {
                this.compileText(node);
            }
        });
    }
    isElement(node) {
        if (node.nodeType === 1) {
            return true;
        }
    }
    isText(node) {
        if (node.nodeType === 3) {
            return true;
        }
    }
    isDirective(attr) {
        if (attr.startsWith("v-")) return true;
    }
    compileElement(node) {
        this.compile(node);
        Array.from(node.attributes).forEach(attr => {
            let attrName = attr.name;
            if (this.isDirective(attrName)) {
                let fnName = attrName.substr(2);
                this.update(node, fnName, attr.value);
            }
        });
    }
    update(node, key, value) {
        let fn = this[`${key}Updater`];
        fn && fn.call(this, node, value);
    }
    textUpdater(node, value) {
        node.textContent = eval(`this.vm.${value}`);
        new Watcher(this.vm, value, newVal => {
            node.textContent = newVal
        })
    }
    modelUpdater(node, value) {
        node.value = eval(`this.vm.${value}`);
        new Watcher(this.vm, value, newVal => {
            node.value = newVal
        })
        node.addEventListener("input", val => {
            this.vm[value] = val.target.value
        });
    }
    compileText(node) {
        const reg = /\{\{(.+?)\}\}/g;
        let value = node.textContent;
        if (reg.test(value)) {
            let key = RegExp.$1;
            node.textContent = eval(`this.vm.${key}`);
            new Watcher(this.vm, key, newValue => {
                node.textContent = newValue;
            });
        }
    }
}
